home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
More Source
/
Pascal
/
sndDemo
/
sndDemo.p
< prev
next >
Wrap
Text File
|
1995-06-15
|
7KB
|
173 lines
program sndDemo;
{ I spent a hard week getting this demo of the playing of an asynchronous sound to work }
{ in Think Pascal 4.0.2. My main difficulty was that it won't work with the [D] Debug switch set }
{ on the compile options. But the manual doesn't contain all of the necessary information. }
{ Some essential ideas were gleaned from Jim Reekes' pSoundApp example in the DTS folder }
{ of ftp.apple.com. Since it was so touchy, I thought others might benefit from this demo. }
{ }
{ This code is terse. I have stripped out everything but the essentials. It should be used }
{ in conjuntion with chapter 22 of volume VI of Inside Macintosh. I have deliberately left }
{ out all error checking so as to not obscure the essential code. Although in all my testing }
{ I never saw an error that wasn't a result of my stupidity or ignorance. I have included a }
{ few extra inline procedure declarations to make it easier to build this demo into a real program. }
{ }
{ To play an asynchronous sound - that is, a sound that plays while other things are happening, }
{ one must define a callBack procedure. This procedure can't do much because it will be invoked }
{ at interrupt time and won't have access to your normal program environment. To access your }
{ global variables, you must restore register A5. Most of the callBack code is concerned with }
{ restoring A5; and all the callback procedure does is set a switch 'sndProgress := 2' so that you }
{ can tell (elsewhere) that the sound has finished. }
{ }
{ Two global variables are needed: }
{ - The integer sndProgress is meant to have the value 0 when no sound is playing, 1 when a sound}
{ is playing, and 2 when a sound has finished but the resources haven't been released yet. }
{ - The sndChannelPtr mySndChannel is given a value when a sound channel is allocated in the }
{ routine that starts the sound playing (aSyncStartPlay), and is needed to dispose of the channel }
{ when the sound has completed and must be disposed (aSyncEndPlay). }
{ }
{ If you use these routines to play async sounds, you will want a line of code in your main}
{ event loop to dispose of the channel and sound handle as soon as the sound has completed:}
{ if sndProgress = 2 then }
{ aSyncEndPlay(sndChannel); }
{ }
{ What this demo program does, is start the sound playing and then count until the sound is done. }
{ The count is written to the text window. It does this five times. You must open the window manually }
{ and place it strategically if you want to watch the counting as the sound is played. }
{ ------------------------------------------------------------------------------------------ }
{ Marv Westrom }
{ Mathematics and Science Education (Computing Studies Education) }
{ The University of British Columbia }
{ Vancouver, B.C. Canada V6T 1Z4 }
{ ------------------------------------------------------------------------------------------ }
{ March 24, 1993.}
{ ------------------------------------------------------------------------------------------ }
{--- Changes by Ingemar Ragnemalm june 1994. ---}
{}
{All I've done is to change capitalization of some constant and procedure names to conform better to the}
{ standards of Mac programming: procedures and types first letter upper-case, variables and constants}
{ not, constants should start with "k", globals variables with "g". How "integer" and "longint" should look,}
{ I'm not 100% sure - everybody does it different, it seems.}
{}
{ I also compressed the sound 3:1, making the total archive REALLY small.}
{}
{A little warning: This code seems quite ok, but you may want to know a few things when using it:}
{- You don't really have to have a callback procedure, if you don't care exactly when the previous sound}
{finishes playing. Even then, you can use SndChannelStatus instead. You can stop the previous sound by}
{disposing the channel.}
{- You will get more speed if you don't dispose the channel after every sound, BUT that will increase}
{the risk of crashes when using Sound Manager older than version 3.0 (and there are LOTS of Macs}
{that aren't updated yet!!!) So if you want to get speed up, beware… Of course, some take the easy way}
{out and don't guarantee anything with old SM.}
{}
{Finally, including Sound.p in the project, and "uses Sound" in the beginning, is usually preferrable over}
{copying in a bunch of the declarations.}
uses
{$IFC UNDEFINED THINK_PASCAL}
Types, QuickDraw, Events, Menus, Dialogs, Fonts, Resources, Devices,
{$ENDC}
Sound;
const
kNoSynth = 0; { no specified synth for channel }
kInitNone = 0; { no specified init parameters for channel }
var { necessary globals }
gMySndChannel: SndChannelPtr;
gSndProgress: integer;
{$PUSH}
{$D-}
procedure MyCallBack (Chan: sndChannelPtr; cmd: sndCommand);
var
myA5: longint;
begin
if cmd.param1 = 99 then
begin
myA5 := SetA5(cmd.param2);
gSndProgress := 2;
myA5 := SetA5(myA5);
end;
end;
{$POP}
procedure AsyncStartPlay (sndH: handle);
var
mySndCmd: sndCommand;
myErr: OSErr;
begin
LoadResource(sndH);
MoveHHi(sndH);
Hlock(sndH);
gMySndChannel := nil;
myErr := SndNewChannel(gMySndChannel, kNoSynth, kInitNone, @MyCallBack);
{$IFC UNDEFINED THINK_PASCAL}
myErr := SndPlay(gMySndChannel, SndListHandle(sndH), true);
{$ELSEC}
myErr := SndPlay(gMySndChannel, sndH, true);
{$ENDC}
gSndProgress := 1;
mySndCmd.cmd := 13; { callBackCmd }
mySndCmd.param1 := 99; { arbitrary code to check MyCallback }
mySndCmd.param2 := SetCurrentA5;
myErr := SndDoCommand(gMySndChannel, mySndCmd, false);
end;
procedure AsyncEndPlay (sndH: handle);
var
mySndCmd: sndCommand;
myErr: OSErr;
begin
mySndCmd.cmd := 3; { quietCmd }
myErr := SndDoCommand(gMySndChannel, mySndCmd, false);
myErr := SndDisposeChannel(gMySndChannel, true);
HUnlock(sndH);
gSndProgress := 0;
end;
procedure InitMacintosh;
begin
{$IFC UNDEFINED THINK_PASCAL}
MaxApplZone;
InitGraf(@qd.thePort);
InitFonts;
FlushEvents(everyEvent, 0);
InitWindows;
InitMenus;
TEInit;
InitDialogs(nil);
{$ENDC}
InitCursor;
end; {InitMacintosh}
{Variables that are local to the main procedure.}
var
sndHiThere: Handle;
i, times: integer;
begin
InitMacintosh;
gSndProgress := 0;
sndHiThere := GetNamedResource('snd ', 'Hi There');
{$IFC DEFINED THINK_PASCAL}
ShowText;
{$ENDC}
for times := 1 to 5 do
begin
writeln;
writeln('Hi there ', times : 2);
AsyncStartPlay(sndHiThere);
i := 0;
repeat
i := i + 1;
write(i : 3);
if (i mod 25) = 0 then
writeln;
until gSndProgress = 2;
AsyncEndplay(sndHiThere);
end;
end.